package com.hdu.dwh.pojos.SQLBuilder;

import java.util.Map;
import java.util.Set;

import com.hdu.dwh.pojos.source_access_pojos.IColumn;
import com.hdu.dwh.utils.StatementUtils;

import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode(callSuper = false)
public class SQLCreateTableBuilder extends SQLBulder {
    private String tableName;
    private String databaseName;
    private Set<String> primaryKeys;
    private Set<String> partitionKeys;
    private Set<IColumn> columns;
    private Map<String, String> tableOptions;

    public SQLCreateTableBuilder(String databaseName, String tableName, Set<IColumn> columns) {
        this.databaseName = databaseName;
        this.tableName = tableName;
        this.columns = columns;
    }

    public SQLCreateTableBuilder withPrimaryKeys(Set<String> primaryKeys) {
        this.primaryKeys = primaryKeys;
        return this;
    }

    public SQLCreateTableBuilder withPartitionKeys(Set<String> partitionKeys) {
        this.partitionKeys = partitionKeys;
        return this;
    }

    public SQLCreateTableBuilder withTableOptions(Map<String, String> tableOptions) {
        this.tableOptions = tableOptions;
        return this;
    }

    // PRIMARY KEY (dt, hh, user_id) NOT ENFORCED
    private String PrimaryKeyPart() {
        if (primaryKeys == null || primaryKeys.size() == 0) {
            return "";
        }
        return "PRIMARY KEY (" + String.join(", ", primaryKeys) + ") NOT ENFORCED";
    }

    // user_id BIGINT,
    // item_id BIGINT,
    // behavior STRING,
    // dt STRING,
    // hh STRING,
    // PRIMARY KEY (dt, hh, user_id) NOT ENFORCED
    private String ColumnsPart() {
        StringBuilder sb = new StringBuilder();
        for (IColumn column : columns) {
            if (column.getColumnName() == null || column.getColumnType() == null) {
                throw new IllegalArgumentException("Column name or type is null");
            }
            sb.append(column.getColumnName()).append(" ").append(column.getColumnType()).append(",\n");
        }
        if (primaryKeys != null && primaryKeys.size() > 0) {
            sb.append(PrimaryKeyPart()).append("\n");
        } else {
            // remove last comma
            sb.deleteCharAt(sb.length() - 2);
        }
        return sb.toString();
    }

    private String PartitionPart() {
        if (partitionKeys == null || partitionKeys.size() == 0) {
            return "";
        }
        return "PARTITIONED BY (" + String.join(", ", partitionKeys) + ")\n";
    }

    public String build() {
        StringBuilder sb = new StringBuilder();
        sb.append("CREATE TABLE ").append(StatementUtils.quote(databaseName)).append(".").append(StatementUtils.quote(tableName)).append(" (\n");
        sb.append(ColumnsPart());
        sb.append(")\n");
        sb.append(PartitionPart());
        if (tableOptions != null && tableOptions.size() > 0) {
            sb.append("WITH (\n");
            for (Map.Entry<String, String> entry : tableOptions.entrySet()) {
                sb.append("'").append(entry.getKey()).append("' = '").append(entry.getValue()).append("',\n");
            }
            // remove last comma
            sb.deleteCharAt(sb.length() - 2);
            sb.append(")\n");
        }
        return sb.toString();
    }

}
